﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;

namespace TerrainProcessor
{
    public class HeightmapInfoContent
    {
        public float[,] height;
        public Vector3[,] normals;
        public float terrainScale;
        public HeightmapInfoContent(MeshContent terrainMesh, PixelBitmapContent<float> bitmap, float terrainScale, float terrainBumpiness)
        {
            this.terrainScale = terrainScale;

            height = new float[bitmap.Width, bitmap.Height];
            normals = new Vector3[bitmap.Width, bitmap.Height];

            //for (int y = 0; y < bitmap.Height; y++)
            //{
            //    for (int x = 0; x < bitmap.Width; x++)
            //    {
            //        height[x, y] = (bitmap.GetPixel(x, y) - 1) * terrainBumpiness;
            //    }
            //}


            // to fill those arrays, we'll look at the position and normal data
            // contained in the terrainMesh.
            GeometryContent geometry = terrainMesh.Geometry[0];
            // we'll go through each vertex....
            for (int i = 0; i < geometry.Vertices.VertexCount; i++)
            {
                // ... and look up its position and normal.
                Vector3 position = geometry.Vertices.Positions[i];
                Vector3 normal = (Vector3)geometry.Vertices.Channels[VertexChannelNames.Normal()][i];

                // from the position's X and Z value, we can tell what X and Y
                // coordinate of the arrays to put the height and normal into.
                int arrayX = (int)((position.X / terrainScale) + (bitmap.Width - 1) / 2.0f);
                int arrayY = (int)((position.Z / terrainScale) + (bitmap.Height - 1) / 2.0f);

                height[arrayX, arrayY] = position.Y;
                normals[arrayX, arrayY] = normal;
            }




        }
    }

    [ContentTypeWriter]
    public class HeightMapInfoWriter : ContentTypeWriter<HeightmapInfoContent>
    {
        protected override void Write(ContentWriter output, HeightmapInfoContent value)
        {
            output.Write(value.terrainScale);
            output.Write(value.height.GetLength(0));
            output.Write(value.height.GetLength(1));
            foreach (float height in value.height)
            {
                output.Write(height);
            }
            foreach (Vector3 normal in value.normals)
            {
                output.Write(normal);
            }

        }

        public override string GetRuntimeType(TargetPlatform targetPlatform)
        {
            return "TerrainProcessor.HeightMapInfo, " + "TerrainProcessor, Version=1.0.0.0, Culture=neutral";
        }

        public override string GetRuntimeReader(TargetPlatform targetPlatform)
        {
            return "TerrainProcessor.HeightMapInfoReader, " + "TerrainProcessor, Version=1.0.0.0, Culture=neutral";
        }

    }

}
